package com.sjd.mall.service.order.impl;

import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.sjd.common.constant.GoldenBeanConstants;
import com.sjd.common.core.domain.AjaxResult;
import com.sjd.common.utils.OrderNoUtils;
import com.sjd.mall.domain.SjdAccountAddrDO;
import com.sjd.mall.domain.SjdGoodsDO;
import com.sjd.mall.domain.SjdGoodsTypeDO;
import com.sjd.mall.domain.SjdOrderDO;
import com.sjd.mall.domain.SjdOrderItemsDO;
import com.sjd.mall.domain.SjdShoppingCartDO;
import com.sjd.mall.domain.dto.base.BaseGoodsVO;
import com.sjd.mall.domain.dto.base.OrderNoRequestDTO;
import com.sjd.mall.domain.dto.order.WxCourierQryResponseDTO;
import com.sjd.mall.domain.dto.order.WxOrderCreateCartRequestDTO;
import com.sjd.mall.domain.dto.order.WxOrderCreateRequestDTO;
import com.sjd.mall.domain.dto.order.WxOrderCreateResponseDTO;
import com.sjd.mall.domain.dto.order.WxOrderQryRequestDTO;
import com.sjd.mall.domain.dto.order.WxOrderQryResponseDTO;
import com.sjd.mall.enums.GoodsClass;
import com.sjd.mall.enums.OrderStatus;
import com.sjd.mall.mapper.SjdAccountAddrMapper;
import com.sjd.mall.mapper.SjdGoodsMapper;
import com.sjd.mall.mapper.SjdGoodsTypeMapper;
import com.sjd.mall.mapper.SjdOrderItemsMapper;
import com.sjd.mall.mapper.SjdOrderMapper;
import com.sjd.mall.mapper.SjdShoppingCartMapper;
import com.sjd.mall.service.account.AccountGoldenBeanService;
import com.sjd.mall.service.goods.GoodsService;
import com.sjd.mall.service.order.WxOrderService;
import com.sjd.wx.utils.ThirdSessionHolder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.MutablePair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 订单
 *
 * @author seer
 * @version 1.0
 * @date 2022/1/13 10:54
 */
@Slf4j
@Service
public class WxOrderServiceImpl implements WxOrderService {

    @Autowired
    private SjdOrderMapper orderMapper;

    @Autowired
    private SjdOrderItemsMapper orderItemsMapper;

    @Autowired
    private SjdShoppingCartMapper shoppingCartMapper;

    @Autowired
    private SjdGoodsMapper goodsMapper;

    @Autowired
    private SjdGoodsTypeMapper goodsTypeMapper;

    @Autowired
    private SjdAccountAddrMapper accountAddrMapper;

    @Autowired
    private GoodsService goodsService;

    @Autowired
    private WxOrderService orderService;

    @Autowired
    private AccountGoldenBeanService accountService;

    /**
     * 快递状态
     */
    private final static HashMap<String, String> COURIER_STATE = new HashMap<>();

    /**
     * 订单创建
     *
     * @param requestDTO requestDTO
     * @return object
     */
    @Override
    public AjaxResult create(WxOrderCreateRequestDTO requestDTO) {
        List<MutablePair<Long, BigDecimal>> goods = Lists.newArrayList(new MutablePair<>(requestDTO.getGoodsId(), requestDTO.getGoodsQuantity()));
        return orderService.baseCreate(requestDTO.getAddressId(), goods);
    }

    /**
     * 订单创建
     * 购物车
     *
     * @param requestDTO requestDTO
     * @return object
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult createCart(WxOrderCreateCartRequestDTO requestDTO) {
        List<MutablePair<Long, BigDecimal>> goodList = new ArrayList<>();
        for (Long cartId : requestDTO.getShoppingCartIds()) {
            SjdShoppingCartDO cart = shoppingCartMapper.getById(cartId);
            goodList.add(new MutablePair<>(cart.getGoodsId(), cart.getGoodsQuantity()));
        }
        AjaxResult result = orderService.baseCreate(requestDTO.getAddressId(), goodList);
        if (result.isSuccess()) {
            // 删除购物车
            shoppingCartMapper.deletes(requestDTO.getShoppingCartIds());
        }
        return result;
    }

    /**
     * 订单支付
     *
     * @param requestDTO requestDTO
     * @return object
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult pay(OrderNoRequestDTO requestDTO) {
        SjdOrderDO orderDO = orderMapper.getByOrderNo(requestDTO.getOrderNo());
        Assert.notNull(orderDO, "订单不存在 " + requestDTO.getOrderNo());
        if (!OrderStatus.CREATE_SUCCESS.value.equals(orderDO.getOrderStatus())) {
            return AjaxResult.error("订单状态异常,禁止支付");
        }
        boolean timeout = orderDO.getPaymentDeadline().compareTo(LocalDateTime.now()) < 0;
        if (timeout) {
            return AjaxResult.error("订单超时,禁止支付");
        }
        // 金豆支付
        String orderType = GoodsClass.GOODS == orderDO.getGoodsClass() ? GoldenBeanConstants.CONSUME_CROPS : GoldenBeanConstants.CONSUME_COURSE;
        String remark = "商城订单：" + orderDO.getOrderNo();
        AjaxResult result = accountService.createConsumeOrRefoundOrder(orderType, orderDO.getPayableAmount().intValue(), remark);
        if (!result.isSuccess()) {
            log.warn("订单支付失败 {}", result.get(AjaxResult.MSG_TAG));
            return result;
        }

        // 修改订单状态
        SjdOrderDO update = new SjdOrderDO();
        update.setOrderStatus(OrderStatus.PAY_SUCCESS.value);
        update.setOrderStatusTime(LocalDateTime.now());
        update.setPaymentAmount(orderDO.getPayableAmount());
        update.setPaymentTime(LocalDateTime.now());
        update.setOrderNo(orderDO.getOrderNo());
        orderMapper.updateSelectiveByOrderNo(update);
        return AjaxResult.success();
    }

    /**
     * 订单查询
     *
     * @param requestDTO requestDTO
     * @return object
     */
    @Override
    public List<WxOrderQryResponseDTO> qry(WxOrderQryRequestDTO requestDTO) {
        List<SjdOrderDO> resultList = orderMapper.listByMember(ThirdSessionHolder.getSjdMemberId(), requestDTO.getOrderStatus(), requestDTO.getGoodsClass());
        List<WxOrderQryResponseDTO> responseList = new ArrayList<>();
        for (SjdOrderDO order : resultList) {
            WxOrderQryResponseDTO response = new WxOrderQryResponseDTO();
            response.setId(order.getId());
            response.setOrderNo(order.getOrderNo());
            response.setOrderStatus(order.getOrderStatus());
            response.setOrderStatusLabel(OrderStatus.label(order.getOrderStatus()));
            response.setOrderAmount(order.getOrderAmount());
            response.setOrderTime(order.getOrderTime());
            response.setDiscountAmount(order.getDiscountAmount());
            response.setPaymentAmount(order.getPaymentAmount());
            response.setPaymentTime(order.getPaymentTime());
            response.setReceiverName(order.getReceiverName());
            response.setReceiverMobile(order.getReceiverMobile());
            response.setReceiverAddress(order.getReceiverAddress());
            response.setDeliverTime(order.getDeliverTime());
            response.setCourierNo(order.getCourierNo());
            response.setReceiptTime(order.getReceiptTime());
            response.setRefundTime(order.getRefundTime());
            response.setCancelTime(order.getCancelTime());

            List<SjdOrderItemsDO> itemsList = orderItemsMapper.listByOrderNo(order.getOrderNo());
            List<BaseGoodsVO> respItems = itemsList.stream().map(items -> {
                BaseGoodsVO goodsVO = new BaseGoodsVO();
                goodsVO.setId(items.getId());
                goodsVO.setGoodsId(items.getGoodsId());
                goodsVO.setGoodsQuantity(items.getGoodsQuantity());
                goodsVO.setGoodsName(items.getGoodsName());
                goodsVO.setGoodsPicture(items.getGoodsPicture());
                goodsVO.setGoodsPrice(items.getGoodsPrice());
                goodsVO.setGoodsAmount(items.getGoodsAmount());
                goodsVO.setDiscountAmount(items.getDiscountAmount());
                goodsVO.setPayableAmount(items.getPayableAmount());
                return goodsVO;
            }).collect(Collectors.toList());
            response.setGoodsItems(respItems);
            responseList.add(response);
        }
        return responseList;
    }

    /**
     * 订单退款
     *
     * @param requestDTO requestDTO
     * @return object
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult refund(OrderNoRequestDTO requestDTO) {
        SjdOrderDO orderDO = orderMapper.getByOrderNo(requestDTO.getOrderNo());
        Assert.notNull(orderDO, "订单不存在 " + requestDTO.getOrderNo());
        if (!orderDO.getIsCanRefund()) {
            return AjaxResult.error("此商品订单不允许退款,请联系客服");
        }
        if (OrderStatus.DELIVER_SUCCESS.value.equals(orderDO.getOrderStatus())) {
            return AjaxResult.error("订单已发货,请联系客服");
        }
        if (OrderStatus.RECEIPT_SUCCESS.value.equals(orderDO.getOrderStatus())) {
            return AjaxResult.error("订单已收货,请联系客服");
        }
        if (!OrderStatus.PAY_SUCCESS.value.equals(orderDO.getOrderStatus())) {
            return AjaxResult.error("订单状态异常,禁止退款");
        }
        Duration duration = LocalDateTimeUtil.between(orderDO.getPaymentTime(), LocalDateTime.now());
        boolean cant = duration.compareTo(Duration.ofHours(2L)) > 0;
        if (cant) {
            return AjaxResult.error("超过2小时,请联系客服");
        }

        // 金豆退款
        AjaxResult result = accountService.createConsumeOrRefoundOrder(GoldenBeanConstants.REFOUND, orderDO.getPayableAmount().intValue(), "农作物退款");
        if (!result.isSuccess()) {
            log.warn("订单退款失败 {}", result.get(AjaxResult.MSG_TAG));
            return result;
        }

        List<SjdOrderItemsDO> itemList = orderItemsMapper.listByOrderNo(orderDO.getOrderNo());
        for (SjdOrderItemsDO items : itemList) {
            // 恢复库存
            MutablePair<Boolean, String> pair = goodsService.increaseStorage(items.getGoodsId(), items.getGoodsQuantity());
            if (!pair.getLeft()) {
                log.warn("订单退款失败，恢复库存失败 {} {} {}", items.getGoodsId(), items.getGoodsQuantity(), pair.getRight());
                return AjaxResult.error("退款异常，请联系客服");
            }
        }

        // 修改订单状态
        SjdOrderDO update = new SjdOrderDO();
        update.setOrderStatus(OrderStatus.REFUND_SUCCESS.value);
        update.setOrderStatusTime(LocalDateTime.now());
        update.setRefundTime(LocalDateTime.now());
        update.setOrderNo(requestDTO.getOrderNo());
        orderMapper.updateSelectiveByOrderNo(update);
        return AjaxResult.success();
    }

    /**
     * 订单取消
     *
     * @param orderNo orderNo
     * @return object
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult cancel(String orderNo) {
        SjdOrderDO orderDO = orderMapper.getByOrderNo(orderNo);
        Assert.notNull(orderDO, "订单不存在 " + orderNo);
        if (!OrderStatus.CREATE_SUCCESS.value.equals(orderDO.getOrderStatus())) {
            return AjaxResult.error("订单状态异常,禁止取消");
        }
        SjdOrderDO update = new SjdOrderDO();
        update.setOrderStatus(OrderStatus.CANCEL_SUCCESS.value);
        update.setOrderStatusTime(LocalDateTime.now());
        update.setCancelTime(LocalDateTime.now());
        update.setOrderNo(orderNo);
        orderMapper.updateSelectiveByOrderNo(update);

        List<SjdOrderItemsDO> itemList = orderItemsMapper.listByOrderNo(orderDO.getOrderNo());
        for (SjdOrderItemsDO items : itemList) {
            // 恢复库存
            MutablePair<Boolean, String> pair = goodsService.increaseStorage(items.getGoodsId(), items.getGoodsQuantity());
            if (!pair.getLeft()) {
                log.warn("订单取消失败，恢复库存失败 {} {} {}", items.getGoodsId(), items.getGoodsQuantity(), pair.getRight());
                return AjaxResult.error("订单取消异常，请联系客服");
            }
        }
        return AjaxResult.success();
    }

    /**
     * 订单自动取消,定时任务
     */
    @Override
    public void cancelQuartz() {
        // 查询2h内 订单创建订单
        LocalDateTime startTime = LocalDateTimeUtil.offset(LocalDateTime.now(), -2, ChronoUnit.HOURS);
        List<SjdOrderDO> orderList = orderMapper.listCreate(startTime);
        for (SjdOrderDO orderDO : orderList) {
            log.info("订单支付超时(2h),自动取消 {}", orderDO.getOrderNo());
            AjaxResult result = cancel(orderDO.getOrderNo());
            if (result.isSuccess()) {
                log.info("订单支付超时(2h),取消成功");
            } else {
                log.info("订单支付超时(2h),取消失败 {}", result.get(AjaxResult.MSG_TAG));
            }
        }
    }

    /**
     * 确认收货
     *
     * @param requestDTO requestDTO
     * @return object
     */
    @Override
    public AjaxResult receipt(OrderNoRequestDTO requestDTO) {
        SjdOrderDO orderDO = orderMapper.getByOrderNo(requestDTO.getOrderNo());
        Assert.notNull(orderDO, "订单不存在 " + requestDTO.getOrderNo());
        if (!OrderStatus.DELIVER_SUCCESS.value.equals(orderDO.getOrderStatus())) {
            return AjaxResult.error("订单状态异常,禁止确认收货");
        }
        SjdOrderDO update = new SjdOrderDO();
        update.setOrderStatus(OrderStatus.RECEIPT_SUCCESS.value);
        update.setOrderStatusTime(LocalDateTime.now());
        update.setReceiptTime(LocalDateTime.now());
        update.setOrderNo(requestDTO.getOrderNo());
        orderMapper.updateSelectiveByOrderNo(update);
        return AjaxResult.success();
    }

    /**
     * 订单创建
     *
     * @param addressId addressId
     * @param goodsList goodsPair
     * @return object
     */
    @SuppressWarnings("AlibabaMethodTooLong")
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult baseCreate(Long addressId, List<MutablePair<Long, BigDecimal>> goodsList) {
        // 锁定库存
        for (MutablePair<Long, BigDecimal> pair : goodsList) {
            MutablePair<Boolean, String> result = goodsService.decreaseStorage(pair.getKey(), pair.getValue());
            if (!result.getLeft()) {
                log.warn("创建订单异常，扣减存库失败 {} {} {}", pair.getKey(), pair.getValue(), result.getRight());
                return AjaxResult.error("商品库存不足");
            }
        }

        SjdAccountAddrDO addr = new SjdAccountAddrDO();
        String receiverAddress = "";
        // 课程无收货地址
        if (null != addressId) {
            addr = accountAddrMapper.selectByPrimaryKey(addressId);
            Assert.notNull(addr, "收货地址不存在 " + addressId);
            receiverAddress = addr.getProvince() + "," + addr.getCity() + "," + addr.getArea() + "," + addr.getAddress();
        }
        String orderNo = OrderNoUtils.generateOrderNo(OrderNoUtils.OrderType.BILL_CONSUME);
        log.info("创建订单，生成订单号 {}", orderNo);
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime paymentDeadline = LocalDateTimeUtil.offset(now, 2, ChronoUnit.HOURS);
        // 计算订单价格,保存条目
        List<SjdOrderItemsDO> itemsList = new ArrayList<>();
        BigDecimal orderAmount = BigDecimal.ZERO;
        BigDecimal orderDiscount = BigDecimal.ZERO;
        for (MutablePair<Long, BigDecimal> pair : goodsList) {
            SjdGoodsDO goods = goodsMapper.selectByPrimaryKey(pair.getKey());
            Assert.notNull(goods, "商品不存在 " + pair.getKey());
            BigDecimal goodsAmount = pair.getValue().multiply(goods.getGoodsPrice());
            orderAmount = orderAmount.add(goodsAmount);
            BigDecimal goodsDiscount = goodsService.getMembershipPrice(ThirdSessionHolder.getSjdMemberId(), goodsAmount);
            orderDiscount = orderDiscount.add(goodsDiscount);
            BigDecimal goodsPayable = goodsAmount.subtract(goodsDiscount);

            // 订单条目
            SjdOrderItemsDO items = new SjdOrderItemsDO();
            items.setOrderNo(orderNo);
            items.setGoodsId(goods.getGoodsId());
            items.setGoodsName(goods.getGoodsName());
            items.setGoodsPicture(goods.getBigPicture());
            items.setGoodsQuantity(pair.getValue());
            items.setGoodsPrice(goods.getGoodsPrice());
            items.setGoodsAmount(goodsAmount);
            items.setDiscountAmount(goodsDiscount);
            items.setPayableAmount(goodsPayable);
            items.setGoodsAbstract(getGoodsAbstract(goods));
            orderItemsMapper.insert(items);
            itemsList.add(items);
        }

        BigDecimal orderPayable = orderAmount.subtract(orderDiscount);
        SjdGoodsDO goodsDO = goodsMapper.selectByPrimaryKey(goodsList.get(0).getKey());
        SjdGoodsTypeDO typeDO = goodsTypeMapper.selectByPrimaryKey(goodsDO.getGoodsTypeId());
        boolean refundAble = GoodsClass.GOODS == typeDO.getTypeClass();
        // 创建订单
        SjdOrderDO order = new SjdOrderDO();
        order.setGoodsClass(typeDO.getTypeClass());
        order.setOrderNo(orderNo);
        order.setOrderStatus(OrderStatus.CREATE_SUCCESS.value);
        order.setOrderStatusTime(now);
        order.setMemberId(ThirdSessionHolder.getSjdMemberId());
        order.setMemberMobile(ThirdSessionHolder.getThirdSession().getMobile());
        order.setOrderAmount(orderAmount);
        order.setOrderTime(now);
        order.setDiscountAmount(orderDiscount);
        order.setPayableAmount(orderPayable);
        order.setPaymentDeadline(paymentDeadline);
        order.setReceiverName(addr.getUsername());
        order.setReceiverMobile(addr.getMobile());
        order.setReceiverAddress(receiverAddress);
        order.setIsCanRefund(refundAble);
        orderMapper.insert(order);

        // 响应
        WxOrderCreateResponseDTO response = new WxOrderCreateResponseDTO();
        response.setId(order.getId());
        response.setOrderNo(order.getOrderNo());
        response.setOrderStatus(order.getOrderStatus());
        response.setOrderStatusLabel(OrderStatus.CREATE_SUCCESS.label);
        response.setOrderAmount(order.getOrderAmount());
        response.setOrderTime(order.getOrderTime());
        response.setDiscountAmount(order.getDiscountAmount());
        response.setPayableAmount(order.getPayableAmount());
        response.setPaymentDeadline(order.getPaymentDeadline());
        response.setReceiverName(order.getReceiverName());
        response.setReceiverMobile(order.getReceiverMobile());
        response.setReceiverAddress(order.getReceiverAddress());

        List<BaseGoodsVO> respItems = itemsList.stream().map(items -> {
            BaseGoodsVO goodsVO = new BaseGoodsVO();
            goodsVO.setGoodsId(items.getGoodsId());
            goodsVO.setGoodsQuantity(items.getGoodsQuantity());
            goodsVO.setGoodsName(items.getGoodsName());
            goodsVO.setGoodsPicture(items.getGoodsPicture());
            goodsVO.setGoodsPrice(items.getGoodsPrice());
            goodsVO.setGoodsAmount(items.getGoodsAmount());
            goodsVO.setDiscountAmount(items.getDiscountAmount());
            goodsVO.setPayableAmount(items.getPayableAmount());
            return goodsVO;
        }).collect(Collectors.toList());
        response.setGoodsItems(respItems);
        return AjaxResult.success(response);
    }

    /**
     * 快递查询
     * API {@literal https://api.kuaidi100.com/document/5f0ffb5ebc8da837cbd8aefc}
     *
     * @param requestDTO requestDTO
     * @return object
     */
    @Override
    public AjaxResult courierQry(OrderNoRequestDTO requestDTO) {
        SjdOrderDO orderDO = orderMapper.getByOrderNo(requestDTO.getOrderNo());
        Assert.notNull(orderDO, "订单不存在 " + requestDTO.getOrderNo());

        String key = "DMoRQcTa3509";
        String customer = "3845875B756B032DA42AFFE223DC8CBA";
        String param = String.format("{\"com\":\"%s\",\"num\":\"%s\"}", orderDO.getCourierCompany(), orderDO.getCourierNo());
        String original = param + key + customer;
        String sign = DigestUtils.md5Hex(original).toUpperCase();
        String url = "https://poll.kuaidi100.com/poll/query.do";
        Map<String, Object> reqParam = new HashMap<>(16);
        reqParam.put("customer", customer);
        reqParam.put("sign", sign);
        reqParam.put("param", param);
        String resp = HttpUtil.post(url, reqParam);
        ;
        if (log.isDebugEnabled()) {
            log.debug("快递查询结果 {}", resp);
        }
        if (StringUtils.isEmpty(resp)) {
            return AjaxResult.error("查询结果为空");
        }
        JSONObject object = JSONObject.parseObject(resp);
        boolean notOk = object.containsKey("returnCode") && !"200".equals(object.getString("returnCode"));
        if (notOk) {
            String msg = object.getBoolean("result") + object.getString("returnCode") + object.getString("message");
            return AjaxResult.error(msg);
        }
        String stateLabel = COURIER_STATE.get(object.getString("state"));
        WxCourierQryResponseDTO response = new WxCourierQryResponseDTO();
        response.setStateLabel(stateLabel);
        List<WxCourierQryResponseDTO.Data> dataList = new ArrayList<>();
        for (Object dt0 : object.getJSONArray("data")) {
            JSONObject dtJson = (JSONObject) JSONObject.toJSON(dt0);
            WxCourierQryResponseDTO.Data data = response.new Data();
            data.setTime(dtJson.getString("time"));
            data.setContext(dtJson.getString("context"));
            dataList.add(data);
        }
        response.setDataList(dataList);
        return AjaxResult.success(response);
    }


    /**
     * 获取所有的分类
     *
     * @param goods goods
     * @return object
     */
    private String getGoodsAbstract(SjdGoodsDO goods) {
        SjdGoodsTypeDO goodsType = goodsTypeMapper.selectByPrimaryKey(goods.getGoodsTypeId());
        Assert.notNull(goodsType, "分类不存在 " + goods.getGoodsTypeId());
        List<String> tl = Lists.newArrayList(goodsType.getName());
        while (goodsType.getParentId() != 0) {
            goodsType = goodsTypeMapper.selectByPrimaryKey(goodsType.getParentId());
            tl.add(goodsType.getName());
        }
        JSONObject obj = new JSONObject();
        obj.put("name", goods.getGoodsName());
        obj.put("type", tl);
        return obj.toJSONString();
    }

    {
        COURIER_STATE.put("1", "快件揽件");
        COURIER_STATE.put("101", "已经下快件单");
        COURIER_STATE.put("102", "待快递公司揽收");
        COURIER_STATE.put("103", "快递公司已经揽收");
        COURIER_STATE.put("0", "快件在途中");
        COURIER_STATE.put("1001", "快件到达收件人城市");
        COURIER_STATE.put("1002", "快件处于运输过程中");
        COURIER_STATE.put("1003", "快件发往到新的收件地址");
        COURIER_STATE.put("5", "快件正在派件");
        COURIER_STATE.put("501", "快件已经投递到快递柜或者快递驿站");
        COURIER_STATE.put("3", "快件已签收");
        COURIER_STATE.put("301", "收件人正常签收");
        COURIER_STATE.put("302", "快件显示派件异常,但后续正常签收");
        COURIER_STATE.put("303", "快件已被代签");
        COURIER_STATE.put("304", "快件已由快递柜或者驿站签收");
        COURIER_STATE.put("6", "快件正处于返回发货人的途中");
        COURIER_STATE.put("4", "此快件单已退签");
        COURIER_STATE.put("401", "此快件单已撤销");
        COURIER_STATE.put("14", "收件人拒签快件");
        COURIER_STATE.put("7", "快件转给其他快递公司邮寄");
        COURIER_STATE.put("2", "快件存在疑难");
        COURIER_STATE.put("201", "快件长时间派件后未签收");
        COURIER_STATE.put("202", "快件长时间没有派件或签收");
        COURIER_STATE.put("203", "收件人发起拒收快递,待发货方确认");
        COURIER_STATE.put("204", "快件派件时遇到异常情况");
        COURIER_STATE.put("205", "快件在快递柜或者驿站长时间未取");
        COURIER_STATE.put("206", "无法联系到收件人");
        COURIER_STATE.put("207", "超出快递公司的服务区范围");
        COURIER_STATE.put("208", "快件滞留在网点,没有派送");
        COURIER_STATE.put("209", "快件破损");
        COURIER_STATE.put("8", "快件清关");
        COURIER_STATE.put("10", "快件等待清关");
        COURIER_STATE.put("11", "快件正在清关流程中");
        COURIER_STATE.put("12", "快件已完成清关流程");
        COURIER_STATE.put("13", "货物在清关过程中出现异常");
        COURIER_STATE.put("\\", "收件人拒签快件");
    }
}
